package cn.zyjblogs.netty.groupchat;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * @author zhuyijun
 */
public class GroupChatServerHandler extends SimpleChannelInboundHandler {
    /**
     * 使用map管理
     */
//    private static Map<String,Channel> CHANNEL_MAP = new ConcurrentHashMap<>();
//    private static Map<User,Channel> USER_CHANNEL_MAP = new ConcurrentHashMap<>();

    /**
     * 定义一个Channel组 管理所有的channel
     * GlobalEventExecutor.INSTANCE 全局时间执行器 单例
     */
    private static final ChannelGroup CHANNEL_GROUP = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     *handlerAdded 表示连接建立，一旦链接，第一个被执行
     * 将当前channel加入到channelGroup
     * @param ctx 上下文
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx)  {
        Channel channel = ctx.channel();
        //将该客户端加入两天的信息推送给其他在线的客户端
        //该方法会将channelGroup 中所有channel 遍历，并发送消息
        CHANNEL_GROUP.writeAndFlush("[客户端]"+channel.remoteAddress()+"加入聊天"+" "+SDF.format(new Date()));
        CHANNEL_GROUP.add(channel);
//        CHANNEL_MAP.put("id100",channel);
//        USER_CHANNEL_MAP.put(User.builder().id(10).pwd("123").build(),channel);
    }

    /**
     *
     * @param ctx 上下文
     * @param msg 消息
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
        //获取到当前channel
        Channel channel = ctx.channel();
        //这是我们遍历channelGroup，根据不同的情况，回送不同的消息
        CHANNEL_GROUP.stream().filter(ch -> !ch.equals(channel)).forEach(ch -> ch.writeAndFlush("[客户] "+channel.remoteAddress()+"发送消息 "+" "+SDF.format(new Date())+": "+msg+"\n"));
        channel.writeAndFlush("自己发送了消息"+" "+SDF.format(new Date())+" :"+msg+"\n");
    }

    /**
     * 表示channel处于活动状态 提示xx上线
     * @param ctx 上下文
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println(ctx.channel().remoteAddress()+"上线了~"+" "+SDF.format(new Date()));
    }

    /**
     * 表示channel处于不活动状态，表示xx离线
     * @param ctx 上下文
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        System.out.println(ctx.channel().remoteAddress()+"离线了~"+" "+SDF.format(new Date()));
    }

    /**
     * 表示断开连接 将xx客户的那离开信息推送给当前在线的客户
     * @param ctx 上下文
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        CHANNEL_GROUP.writeAndFlush("[客户端]"+channel.remoteAddress()+"离开了~"+" "+SDF.format(new Date()));
        System.out.println("当前channelGroup的大小"+CHANNEL_GROUP.size());
    }

    /**
     * 发生异常 关闭通道
     * @param ctx 上校问
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }
}
